package com.ruoyi.security.service.backtest.gridtrading.context;

import com.alibaba.fastjson.annotation.JSONField;
import com.ruoyi.security.domain.SecurityDayMinuteTrade;
import com.ruoyi.security.dto.backtest.SecurityGridTradingBacktestParamDto;
import com.ruoyi.security.enums.BenchmarkPriceUpdateTypeEnum;
import com.ruoyi.security.enums.SecurityTradeTypeEnum;
import com.ruoyi.security.service.backtest.gridtrading.strategy.RiseFallTypeCalcStrategy;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * 回测上下文对象
 * 保存回测过程中的状态信息
 * 
 * @author yeoman
 * @date 2025/2/4
 */
@Data
@NoArgsConstructor
public class BacktestContext {

    /**
     * 回测参数
     */
    private BacktestParam backtestParam = new BacktestParam();

    /**
     * 回测变量
     */
    private BacktestVariable backtestVariable = new BacktestVariable();

    @Data
    public static class BacktestParam {
        /**
         * 标的代码
         */
        private String symbol;
        /**
         * 回测周期
         */
        private BacktestPeriod backtestPeriod = new BacktestPeriod();
        /**
         * 交易手续费
         */
        private TradeCharge tradeCharge = new TradeCharge();
        /**
         * 触发及委托设置
         */
        private TriggerMandateSettings triggerMandateSettings = new TriggerMandateSettings();

        /**
         * 初始值
         */
        private InitialValue initialValue = new InitialValue();

        @Data
        public static class BacktestPeriod {
            /**
             * 回测开始时间
             */
            private String startDate;
            /**
             * 回测结束时间
             */
            private String endDate;
        }

        @Data
        public static class TradeCharge {
            /**
             * 券商佣金万分之
             */
            private BigDecimal commissionTenThousandth;
            /**
             * 券商最低佣金
             */
            private BigDecimal minimumCommission;
        }

        @Data
        public static class TriggerMandateSettings {
            /**
             * 涨跌类型
             * @see com.ruoyi.security.enums.RiseFallTypeEnum
             */
            private String riseFallType;

            /**
             * 涨跌类型计算策略
             */
            @JSONField(serialize = false, deserialize = false)
            private RiseFallTypeCalcStrategy riseFallTypeCalcStrategy;

            /**
             * 股价每上涨（按价格差：分；按百分比：%）卖出
             */
            private BigDecimal perRiseValue;

            /**
             * 股价每下跌（按价格差：分；按百分比：%）买入
             */
            private BigDecimal perFallValue;

            /**
             * 基准价更新类型
             * @see BenchmarkPriceUpdateTypeEnum
             */
            private String benchmarkPriceUpdateType;

            /**
             * 单笔买入数量
             */
            private Integer singleBuyQuantity;

            /**
             * 单笔卖出数量
             */
            private Integer singleSellQuantity;

            /**
             * 价格下限（选填）
             */
            private BigDecimal priceFloor;

            /**
             * 价格上限（选填）
             */
            private BigDecimal priceCeiling;
            /**
             * 持仓区间下限（选填）
             */
            private Integer positionFloor;

            /**
             * 持仓区间上限（选填）
             */
            private Integer positionCeiling;

            /**
             * 倍数委托开关
             */
            private Boolean multipleMandateSwitch;
        }

        @Data
        public static class InitialValue {
            /**
             * 初始基准价
             */
            private BigDecimal initialBenchmarkPrice;

            /**
             * 初始持仓
             */
            private Integer initialPosition;

            /**
             * 初始可用资金
             */
            private BigDecimal initialAvailableAmount;

            /**
             * 初始市值
             */
            private BigDecimal initialMarketValue;

            /**
             * 期初总资产
             */
            private BigDecimal initialTotalAssets;
        }
    }

    @Data
    public static class BacktestVariable{
        /**
         * 每上涨/下跌涨跌幅（按价格差：分；按百分比：%）
         */
        private BigDecimal perRiseFallValue;
        /**
         * 当前基准价
         */
        private BigDecimal benchmarkPrice;
        /**
         * 当前触发价
         */
        private BigDecimal triggerPrice;
        /**
         * 当前投入资金（元）
         */
        private BigDecimal investmentAmount;
        /**
         * 最大投入资金（元）
         */
        private BigDecimal maxInvestmentAmount;
        /**
         * 当前可用资金
         */
        private BigDecimal availableAmount;
        /**
         * 总资产值
         */
        private BigDecimal totalAssets;
        /**
         * 当前持仓
         */
        private Integer position;
        /**
         * 当前市值
         */
        private BigDecimal marketValue;

        /**
         * 是否交易标识
         */
        private Boolean tradeFlag;

        /**
         * 当前日期
         */
        private String date;

        /**
         * 交易失败原因
         */
        private String reason;

        /**
         * 交易信息
         */
        private TradeInfo tradeInfo = new TradeInfo();

        /**
         * 日交易信息
         */
        private DayTradeInfo dayTradeInfo = new DayTradeInfo();

        /**
         * 总交易信息
         */
        private TotalTradeInfo totalTradeInfo = new TotalTradeInfo();

        /**
         * 收益信息
         */
        private ProfitInfo profitInfo = new ProfitInfo();

        @Data
        public static class TradeInfo {
            /**
             * 交易价格
             */
            private BigDecimal tradePrice;
            /**
             * 交易数量
             */
            private Integer tradeQuantity;

            /**
             * 交易时间
             */
            private String tradeTime;
            /**
             * 交易类型（买/卖）
             */
            private String tradeType;

            /**
             * 交易倍数
             */
            private Integer tradeMultiple;

            /**
             * 交易金额（元）
             */
            private BigDecimal tradeAmount = BigDecimal.ZERO;
            /**
             * 交易手续费
             */
            private BigDecimal tradeChargeAmount = BigDecimal.ZERO;
        }

        @Data
        public static class DayTradeInfo {

            /**
             * 当日可卖出数量
             */
            private Integer dayCanSellQuantity;
            /**
             * 当日买入信息
             */
            private Buy buy = new Buy();

            /**
             * 当日卖出信息
             */
            private Sell sell = new Sell();

            /**
             * 当日交易信息
             */
            private Trade trade = new Trade();

            /**
             * 收盘价
             */
            private BigDecimal closePrice;

            @Data
            public static class Buy {
                /**
                 * 当日买入次数
                 */
                private Integer dayBuyCount;

                /**
                 * 当日买入数量
                 */
                private Integer dayBuyQuantity;

                /**
                 * 当日买入金额
                 */
                private BigDecimal dayBuyAmount;
                /**
                 * 当日买入手续费
                 */
                private BigDecimal dayBuyChargeAmount;
            }

            @Data
            public static class Sell {
                /**
                 * 当日卖出次数
                 */
                private Integer daySellCount;
                /**
                 * 当日卖出数量
                 */
                private Integer daySellQuantity;
                /**
                 * 当日卖出金额
                 */
                private BigDecimal daySellAmount;
                /**
                 * 当日卖出手续费
                 */
                private BigDecimal daySellChargeAmount;
            }

            @Data
            public static class Trade {
                /**
                 * 当日交易次数
                 */
                private Integer dayTradeCount;

                /**
                 * 当日交易数量
                 */
                private Integer dayTradeQuantity;
                /**
                 * 当日交易金额（元）
                 */
                private BigDecimal dayTradeAmount;
                /**
                 * 当日手续费
                 */
                private BigDecimal dayTradeChargeAmount;
            }
        }

        @Data
        public static class TotalTradeInfo {
            /**
             * 成本价
             */
            private BigDecimal costPrice;

            /**
             * 总买入信息
             */
            private Buy buy = new Buy();

            /**
             * 总卖出信息
             */
            private Sell sell = new Sell();

            /**
             * 总交易信息
             */
            private Trade trade = new Trade();

            @Data
            public static class Buy {
                /**
                 * 买入平均价格
                 */
                private BigDecimal buyAveragePrice = BigDecimal.ZERO;
                /**
                 * 总买入次数
                 */
                private Integer totalBuyCount = 0;

                /**
                 * 总买入数量
                 */
                private Integer totalBuyQuantity = 0;

                /**
                 * 总买入金额（元）
                 */
                private BigDecimal totalBuyAmount = BigDecimal.ZERO;

                /**
                 * 总买入手续费
                 */
                private BigDecimal totalBuyChargeAmount = BigDecimal.ZERO;
            }

            @Data
            public static class Sell {
                /**
                 * 卖出平均价格
                 */
                private BigDecimal sellAveragePrice = BigDecimal.ZERO;
                /**
                 * 总卖出次数
                 */
                private Integer totalSellCount = 0;

                /**
                 * 总卖出数量
                 */
                private Integer totalSellQuantity = 0;

                /**
                 * 总卖出金额（元）
                 */
                private BigDecimal totalSellAmount = BigDecimal.ZERO;

                /**
                 * 总卖出手续费
                 */
                private BigDecimal totalSellChargeAmount = BigDecimal.ZERO;
            }

            @Data
            public static class Trade {
                /**
                 * 总交易次数
                 */
                private Integer totalTradeCount = 0;

                /**
                 * 总交易数量
                 */
                private Integer totalTradeQuantity = 0;

                /**
                 * 总交易金额（元）
                 */
                private BigDecimal totalTradeAmount = BigDecimal.ZERO;

                /**
                 * 总交易手续费
                 */
                private BigDecimal totalTradeChargeAmount = BigDecimal.ZERO;
            }
        }

        @Data
        public static class ProfitInfo {
            /**
             * 总利润
             */
            private BigDecimal totalProfit;
            /**
             * 总收益率（%）- 当前投入
             */
            private BigDecimal totalProfitRateByCurrentInvestment;

            /**
             * 总收益率（%）- 最大投入
             */
            private BigDecimal totalProfitRateByMaxInvestment;
            /**
             * 总收益率（%）- 期初总资产
             */
            private BigDecimal totalProfitRateByInitialTotalAssets;

            /**
             * 一直持有收益
             */
            private BigDecimal alwaysHoldProfit;

            /**
             * 一直持有收益率（%）
             */
            private BigDecimal alwaysHoldProfitRate;

            /**
             * 超额收益率（%）- 当前投入
             */
            private BigDecimal excessProfitRateByCurrentInvestment;
            /**
             * 超额收益率（%）- 最大投入
             */
            private BigDecimal excessProfitRateByMaxInvestment;
            /**
             * 超额收益率（%）- 期初总资产
             */
            private BigDecimal excessProfitRateByInitialTotalAssets;
            /**
             * 最大回撤（%）- 当前投入
             */
            private BigDecimal maxDrawdownByCurrentInvestment;

            /**
             * 最大回撤（%）- 最大投入
             */
            private BigDecimal maxDrawdownByMaxInvestment;

            /**
             * 最大回撤（%）- 期初总资产
             */
            private BigDecimal maxDrawdownByInitialTotalAssets;
        }
    }

    public BacktestContext(SecurityGridTradingBacktestParamDto backtestParamDto, RiseFallTypeCalcStrategy riseFallTypeCalcStrategy) {
        // 标的代码
        backtestParam.symbol = backtestParamDto.getSymbol();
        // 回测周期
        SecurityGridTradingBacktestParamDto.BacktestPeriod backtestPeriod = backtestParamDto.getBacktestPeriod();
        backtestParam.backtestPeriod.startDate = backtestPeriod.getStartDate();
        backtestParam.backtestPeriod.endDate = backtestPeriod.getEndDate();

        // 券商佣金万分之（默认万2.5元）
        backtestParam.tradeCharge.commissionTenThousandth = backtestParamDto.getTradeCharge().getCommissionTenThousandth();

        // 最低佣金（是否免五）
        if (backtestParamDto.getTradeCharge().getFreeMinimumCommission()) {
            backtestParam.tradeCharge.minimumCommission = BigDecimal.ZERO;
        } else {
            backtestParam.tradeCharge.minimumCommission = new BigDecimal("5");
        }

        // 触发条件
        SecurityGridTradingBacktestParamDto.TriggerCondition triggerCondition = backtestParamDto.getTriggerCondition();
        // 涨跌幅类型（按百分比；按价差）
        backtestParam.triggerMandateSettings.riseFallType = triggerCondition.getRiseFallType();
        // 涨跌类型计算策略
        backtestParam.triggerMandateSettings.riseFallTypeCalcStrategy = riseFallTypeCalcStrategy;
        // 股价每上涨（按价格差：分；按百分比：%）卖出
        backtestParam.triggerMandateSettings.perRiseValue = triggerCondition.getPerRiseValue();
        // 股价每下跌（按价格差：分；按百分比：%）买入
        backtestParam.triggerMandateSettings.perFallValue = triggerCondition.getPerFallValue();
        // 初始基准价
        backtestParam.initialValue.initialBenchmarkPrice = triggerCondition.getInitialBenchmarkPrice();

        // 委托设置
        SecurityGridTradingBacktestParamDto.MandateSettings mandateSettings = backtestParamDto.getMandateSettings();
        // 基准价更新类型（按触发价格；按成交价格）
        backtestParam.triggerMandateSettings.benchmarkPriceUpdateType = mandateSettings.getBenchmarkPriceUpdateType();
        // 初始持仓
        backtestParam.initialValue.initialPosition = mandateSettings.getInitialPosition();
        // 初始可用资金（选填）
        backtestParam.initialValue.initialAvailableAmount = mandateSettings.getInitialAvailableAmount();
        // 每笔买入数量
        backtestParam.triggerMandateSettings.singleBuyQuantity = mandateSettings.getMandateQuantity().getSingleBuyQuantity();
        // 每笔卖出数量
        backtestParam.triggerMandateSettings.singleSellQuantity = mandateSettings.getMandateQuantity().getSingleSellQuantity();

        // 高级设置
        SecurityGridTradingBacktestParamDto.AdvancedSetting advancedSetting = backtestParamDto.getAdvancedSetting();
        // 价格区间上限（选填）
        backtestParam.triggerMandateSettings.priceFloor = Optional.ofNullable(advancedSetting).map(SecurityGridTradingBacktestParamDto.AdvancedSetting::getPriceRange)
                .map(SecurityGridTradingBacktestParamDto.AdvancedSetting.PriceRange::getPriceFloor).orElse(null);
        // 价格区间下限（选填）
        backtestParam.triggerMandateSettings.priceCeiling = Optional.ofNullable(advancedSetting).map(SecurityGridTradingBacktestParamDto.AdvancedSetting::getPriceRange)
                .map(SecurityGridTradingBacktestParamDto.AdvancedSetting.PriceRange::getPriceCeiling).orElse(null);

        // 持仓区间上限（选填）
        backtestParam.triggerMandateSettings.positionCeiling = Optional.ofNullable(advancedSetting).map(SecurityGridTradingBacktestParamDto.AdvancedSetting::getPositionRange)
                .map(SecurityGridTradingBacktestParamDto.AdvancedSetting.PositionRange::getPositionCeiling).orElse(null);
        // 持仓区间下限（选填）
        backtestParam.triggerMandateSettings.positionFloor = Optional.ofNullable(advancedSetting).map(SecurityGridTradingBacktestParamDto.AdvancedSetting::getPositionRange)
                .map(SecurityGridTradingBacktestParamDto.AdvancedSetting.PositionRange::getPositionFloor).orElse(null);
        // 倍数委托（选填）
        backtestParam.triggerMandateSettings.multipleMandateSwitch = Optional.ofNullable(advancedSetting).map(SecurityGridTradingBacktestParamDto.AdvancedSetting::getMultipleMandateSwitch).orElse(null);

        // 初始市值
        backtestParam.initialValue.initialMarketValue = backtestParam.initialValue.initialBenchmarkPrice.multiply(new BigDecimal(backtestParam.initialValue.initialPosition));
        // 期初总资产
        backtestParam.initialValue.initialTotalAssets = backtestParam.initialValue.initialMarketValue.add(Optional.ofNullable(backtestParam.initialValue.initialAvailableAmount).orElse(BigDecimal.ZERO));

        // 当前基准价默认等于初始基准价
        backtestVariable.benchmarkPrice = backtestParam.initialValue.initialBenchmarkPrice;
        // 当前投入资金默认等于初始市值
        backtestVariable.investmentAmount = backtestParam.initialValue.initialMarketValue;
        // 最大投入资金默认等于初始市值
        backtestVariable.maxInvestmentAmount = backtestParam.initialValue.initialMarketValue;
        // 当前可用资金默认等于初始可用资金
        backtestVariable.availableAmount = backtestParam.initialValue.initialAvailableAmount;
        // 当前总资产默认等于初始总资产
        backtestVariable.totalAssets = backtestParam.initialValue.initialTotalAssets;
        // 当前持仓默认等于初始持仓
        backtestVariable.position = backtestParam.initialValue.initialPosition;
    }

    /**
     * 空仓日期列表
     */
    private List<String> emptyPositionDateList = new ArrayList<>();

    public void initDayContext(String date) {
        backtestVariable.date = date;
        // 当前可卖出数量为当前持仓数量
        backtestVariable.dayTradeInfo.dayCanSellQuantity = backtestVariable.position;

        backtestVariable.dayTradeInfo.buy.dayBuyCount = 0;
        backtestVariable.dayTradeInfo.buy.dayBuyQuantity = 0;
        backtestVariable.dayTradeInfo.buy.dayBuyAmount = BigDecimal.ZERO;
        backtestVariable.dayTradeInfo.buy.dayBuyChargeAmount = BigDecimal.ZERO;

        backtestVariable.dayTradeInfo.sell.daySellCount = 0;
        backtestVariable.dayTradeInfo.sell.daySellQuantity = 0;
        backtestVariable.dayTradeInfo.sell.daySellAmount = BigDecimal.ZERO;
        backtestVariable.dayTradeInfo.sell.daySellChargeAmount = BigDecimal.ZERO;

        backtestVariable.dayTradeInfo.trade.dayTradeCount = 0;
        backtestVariable.dayTradeInfo.trade.dayTradeQuantity = 0;
        backtestVariable.dayTradeInfo.trade.dayTradeAmount = BigDecimal.ZERO;
        backtestVariable.dayTradeInfo.trade.dayTradeChargeAmount = BigDecimal.ZERO;
    }

    public void updateProfit(BigDecimal price) {
        //// 更新市值
        //backtestVariable.marketValue = price.multiply(new BigDecimal(backtestVariable.position));
        //// 更新总资产
        //backtestVariable.totalAssets = backtestVariable.marketValue.add(Optional.ofNullable(backtestVariable.availableAmount).orElse(BigDecimal.ZERO));
        // 更新总收益 = (当前价格 - 成本价) * 当前持仓数量
        backtestVariable.profitInfo.totalProfit = price.subtract(backtestVariable.totalTradeInfo.costPrice).multiply(new BigDecimal(backtestVariable.position));
        // 更新总收益率(%) = (当前总收益 / 当前投入资金) * 100
        backtestVariable.profitInfo.totalProfitRateByCurrentInvestment = backtestVariable.profitInfo.totalProfit.divide(backtestVariable.investmentAmount, 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100)).setScale(2, RoundingMode.HALF_UP);
        // 更新最大投入收益率(%) = (当前总收益 / 最大投入金额) * 100
        backtestVariable.profitInfo.totalProfitRateByMaxInvestment = backtestVariable.profitInfo.totalProfit.divide(backtestVariable.maxInvestmentAmount, 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100)).setScale(2, RoundingMode.HALF_UP);
        // 更新总收益率(%) - 期初总资产 = (当前总收益 / 期初总资产) * 100
        backtestVariable.profitInfo.totalProfitRateByInitialTotalAssets = backtestVariable.profitInfo.totalProfit.divide(backtestParam.initialValue.initialTotalAssets, 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100)).setScale(2, RoundingMode.HALF_UP);
        // 一直持有收益
        backtestVariable.profitInfo.alwaysHoldProfit = price.subtract(backtestParam.initialValue.initialBenchmarkPrice).multiply(new BigDecimal(backtestVariable.position));
        // 更新一直持有收益率(%) = ((当前价格 - 初始基准价) / 初始基准价) * 100
        backtestVariable.profitInfo.alwaysHoldProfitRate = price.subtract(backtestParam.initialValue.initialBenchmarkPrice).divide(backtestParam.initialValue.initialBenchmarkPrice, 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100)).setScale(2, RoundingMode.HALF_UP);
        // 更新超额收益率（%）- 当前投入 = 总收益率(%) - 一直持有收益率(%)
        backtestVariable.profitInfo.excessProfitRateByCurrentInvestment = backtestVariable.profitInfo.totalProfitRateByCurrentInvestment.subtract(backtestVariable.profitInfo.alwaysHoldProfitRate);
        // 更新超额收益率（%）- 最大投入 = 最大投入收益率(%) - 一直持有收益率(%)
        backtestVariable.profitInfo.excessProfitRateByMaxInvestment = backtestVariable.profitInfo.totalProfitRateByMaxInvestment.subtract(backtestVariable.profitInfo.alwaysHoldProfitRate);
        // 更新超额收益率（%）- 期初总资产 = 总收益率(%) - 一直持有收益率(%)
        backtestVariable.profitInfo.excessProfitRateByInitialTotalAssets = backtestVariable.profitInfo.totalProfitRateByInitialTotalAssets.subtract(backtestVariable.profitInfo.alwaysHoldProfitRate);
    }

    public void setMinuteContext(SecurityDayMinuteTrade trade) {
        backtestVariable.tradeFlag = true;
        backtestVariable.reason = null;
        backtestVariable.tradeInfo.tradeTime = trade.getTime();
        backtestVariable.tradeInfo.tradeQuantity = null;

        BigDecimal price = trade.getPrice();
        backtestVariable.tradeInfo.tradePrice = price;

        // 不在价格区间不交易
        if (backtestParam.triggerMandateSettings.priceFloor != null && price.compareTo(backtestParam.triggerMandateSettings.priceFloor) < 0) {
            backtestVariable.tradeFlag = false;
            backtestVariable.reason = "不在价格区间";
            return;
        }
        if (backtestParam.triggerMandateSettings.priceCeiling != null && price.compareTo(backtestParam.triggerMandateSettings.priceCeiling) > 0) {
            backtestVariable.tradeFlag = false;
            backtestVariable.reason = "不在价格区间";
            return;
        }

        // 差价：当前价-基准价
        BigDecimal diffPrice = price.subtract(backtestVariable.benchmarkPrice);
        // 差价等于0，不交易
        if (diffPrice.compareTo(BigDecimal.ZERO) == 0) {
            backtestVariable.tradeFlag = false;
            backtestVariable.reason = "差价等于0";
            return;
        }

        // 差价大于0，卖出
        if (diffPrice.compareTo(BigDecimal.ZERO) > 0) {
            backtestVariable.tradeInfo.tradeType = SecurityTradeTypeEnum.SELL.getKey();
            backtestVariable.tradeInfo.tradeQuantity = backtestParam.triggerMandateSettings.singleBuyQuantity;
            backtestVariable.perRiseFallValue = backtestParam.triggerMandateSettings.perRiseValue;
        }
        // 差价小于0，买入
        else if (diffPrice.compareTo(BigDecimal.ZERO) < 0) {
            backtestVariable.tradeInfo.tradeType = SecurityTradeTypeEnum.BUY.getKey();
            backtestVariable.tradeInfo.tradeQuantity = backtestParam.triggerMandateSettings.singleBuyQuantity;
            diffPrice = diffPrice.abs();
            backtestVariable.perRiseFallValue = backtestParam.triggerMandateSettings.perFallValue;
        }

        // 根据价格差计算倍数
        backtestVariable.tradeInfo.tradeMultiple = backtestParam.triggerMandateSettings.riseFallTypeCalcStrategy.calculateMultiple(diffPrice, backtestVariable.benchmarkPrice, backtestVariable.perRiseFallValue, backtestVariable.tradeInfo.tradeType);
        // 交易倍数为0，不交易
        if (backtestVariable.tradeInfo.tradeMultiple == 0) {
            backtestVariable.tradeFlag = false;
            backtestVariable.reason = "交易倍数为0";
            return;
        }
        // 开启了倍数委托
        if (Boolean.TRUE.equals(backtestParam.triggerMandateSettings.multipleMandateSwitch)) {
            backtestVariable.tradeInfo.tradeQuantity = backtestVariable.tradeInfo.tradeMultiple * backtestVariable.tradeInfo.tradeQuantity;
        }

        // 校验数量
        if (SecurityTradeTypeEnum.SELL.getKey().equals(backtestVariable.tradeInfo.tradeType)) {
            // 当日可卖出数量已经为0，当日不再卖出
            if (backtestVariable.dayTradeInfo.dayCanSellQuantity <= 0) {
                backtestVariable.tradeFlag = false;
                backtestVariable.reason = "当日可卖出数量已经为0";
                return;
            }
            // 卖出数量不能大于持仓数量
            if (backtestVariable.tradeInfo.tradeQuantity > backtestVariable.position) {
                backtestVariable.tradeFlag = false;
                backtestVariable.reason = "卖出数量不能大于持仓数量";
                return;
            }
            if (backtestParam.triggerMandateSettings.positionFloor != null && (backtestVariable.position - backtestVariable.tradeInfo.tradeQuantity) < backtestParam.triggerMandateSettings.positionFloor) {
                backtestVariable.tradeFlag = false;
                backtestVariable.reason = "卖出后持仓数量低于下限";
                return;
            }
        }else if (SecurityTradeTypeEnum.BUY.getKey().equals(backtestVariable.tradeInfo.tradeType)) {
            if (backtestVariable.availableAmount != null) {
                BigDecimal availableAmountCalculated = backtestVariable.availableAmount.subtract(price.multiply(new BigDecimal(backtestVariable.tradeInfo.tradeQuantity)));
                // 可用金额不足，不能购买
                if (availableAmountCalculated.compareTo(BigDecimal.ZERO) <= 0) {
                    backtestVariable.tradeFlag = false;
                    backtestVariable.reason = "可用金额不足";
                    return;
                }
            }
            if (backtestParam.triggerMandateSettings.positionCeiling != null && (backtestVariable.position + backtestVariable.tradeInfo.tradeQuantity) > backtestParam.triggerMandateSettings.positionCeiling) {
                backtestVariable.tradeFlag = false;
                backtestVariable.reason = "买入后持仓数量超过上限";
                return;
            }
        }
    }

    /**
     * 更新空仓日期
     */
    public void updateEmptyPositionDate() {
        if (backtestVariable.position == 0 && backtestVariable.dayTradeInfo.dayCanSellQuantity == 0) {
            emptyPositionDateList.add(backtestVariable.date);
        }
    }
}

